﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Markup;

namespace Geometry
{
    public sealed class LineSegment : GObjectBase, IGLine
    {
        public LineSegment()
        {
            UpdateBoundingBox();
        }

        public LineSegment(IGPoint _point1, IGPoint _point2)
        {
            this.StartPoint = _point1;
            this.EndPoint = _point2;
            UpdateBoundingBox();
        }

        protected override void ReleaseDependencies()
        {
            this.StartPoint = null;
            this.EndPoint = null;
        }

        protected override void UpdateBoundingBox()
        {
            base.BoundingBox = new Rect(Point1, Point2);
        }

        private double m_Length;
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public double Length
        {
            get { return m_Length; }
            private set
            {
                if (m_Length == value) return;
                m_Length = value;
                RaisePropertyChanged("Length");
            }
        }

        private IGPoint m_StartPoint;
        [ValueSerializer(typeof(ElementReferenceSerializer))]
        [TypeConverter(typeof(PlaceHolderTypeConverter))]
        public IGPoint StartPoint
        {
            get
            {
                return m_StartPoint;
            }
            set
            {
                if (m_StartPoint == value) return;

                if (m_StartPoint != null) m_StartPoint.PropertyChanged -= _related_PropertyChanged;
                m_StartPoint = value;
                if (m_StartPoint != null) m_StartPoint.PropertyChanged += _related_PropertyChanged;

                RaisePropertyChanged("StartPoint");
                RaisePropertyChanged("Point1");
                UpdateCalculations();
            }
        }

        private IGPoint m_EndPoint;
        [ValueSerializer(typeof(ElementReferenceSerializer))]
        [TypeConverter(typeof(PlaceHolderTypeConverter))]
        public IGPoint EndPoint
        {
            get
            {
                return m_EndPoint;
            }
            set
            {
                if (m_EndPoint == value) return;

                if (m_EndPoint != null) m_EndPoint.PropertyChanged -= _related_PropertyChanged;
                m_EndPoint = value;
                if (m_EndPoint != null) m_EndPoint.PropertyChanged += _related_PropertyChanged;

                RaisePropertyChanged("EndPoint");
                RaisePropertyChanged("Point1");
                UpdateCalculations();
            }
        }

        void _related_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "Position") return;

            UpdateCalculations();
        }

        private void UpdateCalculations()
        {
            if (m_StartPoint.IsNullOrPlaceHolder() || m_EndPoint.IsNullOrPlaceHolder()) return;
            UpdateBoundingBox();

            this.Length = Point.Subtract(Point2, Point1).Length;
            this.Slope = ((Point2.Y - Point1.Y) / (Point2.X - Point1.X));
        }

        #region IGLine Members

        private double m_Slope;
        public double Slope
        {
            get { return m_Slope; }
            private set
            {
                if (value.Equals(m_Slope)) return;
                m_Slope = value;
                RaisePropertyChanged("Slope");
            }
        }

        public Point Point1
        {
            get { return m_StartPoint.Position; }
        }

        public Point Point2
        {
            get { return m_EndPoint.Position; }
        }

        #endregion


    }
}
